﻿/*****************************************************************************
* File			: src.Ship
* Purpose		: Contains Declaration and Implementation for Ship class
* Creation date : April 24, 2009
* Author		: Sami TOUIL
******************************************************************************/
package src 
{
	// Imports
	import flash.display.MovieClip;
	import flash.events.*
	import flash.ui.*
	import flash.filters.*
	

	/**************************************
	* Class		: Ship
	* Purpose	: Logic for ship behavior
	* Parent	: MovieClip
	**************************************/
	public class Ship extends MovieClip
	{
		// Class variables
		private			var nMaxHealth		:int	= 100;	// Maximum HP for our ship
		private			var nCurrentHealth	:int;			// HP for our ship
		
		private			var bSpaceLocked	:Boolean=false; // Boolean used to block fire when space key remain pressed
		
		public 			var nSpeed			:int	=  3;	// Ship velocity
		public static 	var main			:Ship;			// static property to refer to the game instance
		
		public static	var miniBoss		 		= null;	// Current miniboss
		
		private			var	bInitialMove	:Boolean;		// True if the ship is arriving
		public			var	bFinalMove	    :Boolean;		// True if the ship is arriving
		
		private 		var bShaking		:Boolean=false;	// Is the ship shaking ?
		private			var nShakeDuration	:int;			// Shake duration
		
		public			var module1			:Module;		// First module
		public			var module2			:Module;		// Second module	
		
		// Constructor
		public function Ship()
		{
			// Set main instance
			main = this;
			
			// Initialize initial and final moves
			bInitialMove = true;
			bFinalMove = false;
			
			// Set modules to null
			module1 = null;
			module2 = null;
			
			// Set listener for ENTER_FRAME event
			addEventListener(Event.ENTER_FRAME, enterFrame);
			cacheAsBitmap = true;
			
			//add some listeners for key presses
			Game.main.stage.addEventListener(KeyboardEvent.KEY_DOWN	, keyDownHandler);
			Game.main.stage.addEventListener(KeyboardEvent.KEY_UP	, keyUpHandler);
			
			// Set coords
			x = -100;
			y = Game.HEIGHT / 2;
			
			// Reset health
			resetHealth();
			
			// add a dropshadow filter 
			var filter:BitmapFilter = new DropShadowFilter(3,45,0x000000,30,5,5);
           	filters = [filter];
		}
		
		/***********************************************************
		* Method		: enterFrame
		* Purpose		: frame loop
		* Parameters	: e:Event
		* return		: void
		***********************************************************/
		public function enterFrame(e:Event)
		{
			// InitialMove (enterring stage)
			if (bInitialMove)
			{
				initialMove();
			}
			// Final move (leaving stage)
			else if (bFinalMove)
			{
				finalMove();
			}
			else
			{
				// Ship management
				moveShip();
				
				// Sip shaking management
				if(bShaking == true)
					shake();
			}
		}
		
		/***********************************************************
		* Method		: keyDownHandler
		* Purpose		: event for key press
		* Parameters	: e:KeyboardEvent : the keyboard event
		* return		: void
		***********************************************************/
		public function keyDownHandler(e:KeyboardEvent)
		{			
			//if spacebar is pressed and is not currently, space bar fires bullet
			if(e.keyCode == Keyboard.SPACE && bSpaceLocked==false && !bInitialMove && !bFinalMove)
			{
				// lock the spacebar until it is released in the keyUphandler, this allows only one bullet to fire at a time
				bSpaceLocked=true;
				
				// Create Missile instance
				new Missile(x + 20, y, 10);
				
				// create missile for eventual modules
				if (module1 != null)
					new Missile(x + 20, y + 20, -8);
				if (module2 != null)
					new Missile(x + 20, y - 20, -4);
			}		
		}
		
		/***********************************************************
		* Method		: keyUpHandler
		* Purpose		: event for when a key is released
		* Parameters	: e:KeyboardEvent : the keyboard event
		* return		: void
		***********************************************************/
		public function keyUpHandler(e:KeyboardEvent)
		{
			//when the spacebar is released
			if(e.keyCode == Keyboard.SPACE && !bInitialMove && !bFinalMove)
			{
				//unlock it so another bullet can be fired when it's pressed again
				bSpaceLocked=false;
			}
		}
		
		/***********************************************************
		* Method		: initialMove
		* Purpose		: Manage the ship initial arrival
		* Parameters	: None
		* return		: void
		***********************************************************/
		public function initialMove():void
		{
			// Move forward
			x += nSpeed;
			
			// When arriving to x = 50, leave initialMove sequence
			if (x > 50)
			{
				bInitialMove = false;
			}
		}
		
		/***********************************************************
		* Method		: finalMove
		* Purpose		: Manage the ship final move
		* Parameters	: None
		* return		: void
		***********************************************************/
		public function finalMove():void
		{			
			// Move forward
			x += nSpeed * 3;
			
			// Delete all Enemy instances
			Enemy.onTakeDamageAll();
			
			// When arriving to x = Game.WIDTH + 100, destroy ship and leave finalMove sequence
			if (x > Game.WIDTH + 100)
			{
				bFinalMove = false;
				onDelete();
			}
		}
		
		/***********************************************************
		* Method		: moveShip
		* Purpose		: Manage the ship position controls
		* Parameters	: None
		* return		: void
		***********************************************************/
		public function moveShip():void
		{			
			// On pressing "Right" key : go forward
			if( Key.isDown(Keyboard.RIGHT) && x < Game.WIDTH - 30)
				x += nSpeed;
			
			// On pressing "Left" key : go backward
			if( Key.isDown(Keyboard.LEFT)  && x > 30 )
				x -= nSpeed;
			
			// On pressing "Up" key : go up
			if( Key.isDown(Keyboard.UP) && y > 50)
				y -= nSpeed;
			
			// On pressing "Down" key : go down
			if( Key.isDown(Keyboard.DOWN) && y < Game.HEIGHT - 20 )
				y += nSpeed;
		}
		
		/***********************************************************
		* Method		: initShake
		* Purpose		: Initialize shaking parameters of the ship
		* Parameters	: None
		* return		: void
		***********************************************************/
		function initShake()
		{
			bShaking = true;
			nShakeDuration = 20;
			rotation = 5;
		}
		
		/***********************************************************
		* Method		: shake
		* Purpose		: Manage the shaking of the ship
		* Parameters	: None
		* return		: void
		***********************************************************/
		function shake()
		{
			rotation *= -1;
			nShakeDuration -= 1;
			if(nShakeDuration == 0)
			{
				bShaking = false;
				rotation = 0;
			}
		}
		
		/***********************************************************
		* Method		: onDelete
		* Purpose		: called for deleting the object instance
		* Parameters	: None
		* return		: void
		***********************************************************/
		public function onDelete()
		{
			// Explosion
			new Explosion(x	, y);
			
			// remove modules
			if (module1 != null)
				module1.onDelete();
			if (module2 != null)
				module2.onDelete();
			
			//remove the ENTER_FRAME event
			removeEventListener(Event.ENTER_FRAME, enterFrame);
			
			//remove keyboard listeners
			Game.main.stage.removeEventListener(KeyboardEvent.KEY_DOWN	, keyDownHandler);
			Game.main.stage.removeEventListener(KeyboardEvent.KEY_UP	, keyUpHandler);
			
			// Delete all Enemy instances
			Enemy.onDeleteAll();
			
			//remove this ship from the stage
			Game.main.spriteClip.removeChild(this);
			Game.main.ship = null;
		}
				
		/***********************************************************
		* Method		: updateHealth
		* Purpose		: Update ship health
		* Parameters	: nPoints:int : The HP we want to add/remove
		* return		: void
		***********************************************************/
		public function updateHealth(nPoints:int)
		{
			nCurrentHealth += nPoints;
			
			if (nCurrentHealth < 0)
				nCurrentHealth = 0;
				
			if (nCurrentHealth > nMaxHealth)
				nCurrentHealth = nMaxHealth;
				
			Game.main.hpMeter.bar.scaleX = nCurrentHealth / nMaxHealth;
				
			// If HP = 0, delete ship and show Gameovermenu
			if (nCurrentHealth == 0)
			{
				onDelete();
				Game.main.gameOver();
			}
		}
		
		/***********************************************************
		* Method		: resetHealth
		* Purpose		: Reset ship health
		* Parameters	: None
		* return		: void
		***********************************************************/
		public function resetHealth()
		{
			nCurrentHealth = nMaxHealth;
			Game.main.hpMeter.bar.scaleX = 1;
		}
	}
}